# 定义函数
'''
def aa():
    print("1:aaaa")
    print("2:aaaa")
    print("3:aaaa")
# 调用函数
# aa()

def stu(name='zhangsan',age=20,sex='man'):
    print("姓名:{},年龄:{},性别:{}".format(name,age,sex))

stu()
stu("lisi")
stu("wangwu",37)
stu("zhaoliu",40,'women')
stu("zhaoliu",'women',40)
stu("zhaoliu",sex='women',age=40)

def demo(*arg):
    print(arg)

demo(10,20)

def demo1(**arg):
    print(arg)

demo1(name='zhangsan',age=20)

def demo2(m,**arg):
    print(m)
    print(arg)

demo2(10,name='zhangsan',age=20)

sum=lambda v1,v2:v1+v2

print(sum(10,20))
'''

#返回多值
def getNames():
    return 'yh',"hhh"
name1,name2=getNames() #其实就是元组，省略了括号
print(name1,name2)

t=getNames()
print(type(t)) #<class 'tuple'>

#可变参数
def my_sum(*nums):
    sum=0
    for n in nums:
        sum = sum+n
    return sum

print(my_sum(2,3,4))

#通过List调用可变参数
nums = [1,2,3]
print(my_sum(*nums)) #可变参数记得加*

#关键字参数    就是可以带关键字作为参数
def student(name,age,**kw):
    print('name:',name,'age:',age,'other:',kw)
student('hh',18,sex='male',region='china')  #name和age 一点要写，其他科协可不写
#name: hh age: 18 other: {'sex': 'male', 'region': 'china'}   其他的变成字典

# 通过字典传入
dicts={'city':"beijing",'sex':'femail'}
student('mike',28,**dicts)
# name: mike age: 28 other: {'city': 'beijing', 'sex': 'femail'}

def students(name,age,*,city): #也是关键字参数，指*后面的参数可写可不写
    print('name:',name,'age:',age,'city:',city)
# students('kk',22,city='gz',mail='nan') 报错

# 局部变量全局变量
name='kong'
def fun():
    global name  #如果不声明全局，下面的lisi会报错，以为是局部变量
    print('输出全局变量',name)#输出全局变量 kong
    name='lisi'

fun()
print('函数外的全局变量name=',name) #函数外的全局变量name= lisi

#斐波那契数列
# 简单版 接在 fab 函数中用 print 打印数字会导致该函数可复用性较差，
# 因为 fab 函数返回 None，其他函数无法获得该函数生成的数列
def fab1(max):
   n, a, b = 0, 0, 1
   while n < max:
       print(b)
       a, b = b, a + b
       n = n + 1
# 进阶版 该函数在运行中占用的内存会随着参数 max 的增大而增大，如果要控制内存占用，最好不要用 List
#
# 来保存中间结果，而是通过 iterable 对象来迭代
def fab2(max):
   n, a, b = 0, 0, 1
   L = []
   while n < max:
       L.append(b)
       a, b = b, a + b
       n = n + 1
   return L

# 最终版   代码远远没有第一版的 fab 函数来得简洁。
# 如果我们想要保持第一版 fab 函数的简洁性，
# 同时又要获得 iterable 的效果，yield 就派上用场了
class Fab(object):

    def __init__(self, max):
        self.max = max
        self.n, self.a, self.b = 0, 0, 1

    def __iter__(self):
        return self

    def next(self):
        if self.n < self.max:
            r = self.b
            self.a, self.b = self.b, self.a + self.b
            self.n = self.n + 1
            return r
        raise StopIteration()

# 最终版  yield 的作用就是把一个函数变成一个 generator，
# 带有 yield 的函数不再是一个普通函数，Python 解释器会
# 将其视为一个 generator，调用 fab(5) 不会执行 fab 函数，
# 而是返回一个 iterable 对象！在 for 循环执行时，每次循
# 环都会执行 fab 函数内部的代码，执行到 yield b 时，fab
# 函数就返回一个迭代值，下次迭代时，代码从 yield b 的下
# 一条语句继续执行，而函数的本地变量看起来和上次中断执行
# 前是完全一样的，于是函数继续执行，直到再次遇到 yield
def fab3(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        # print b
        a, b = b, a + b
        n = n + 1

f3 = fab3(5)
for i in f3:
    print(i)
